home *** CD-ROM | disk | FTP | other *** search
/ CICA 1995 September (Japanese) / CICA Shareware for Windows CD-ROM (Walnut Creek) (September 1995) (Japanese) (Disc 2).iso / disc2 / nt / ntperf.exe / PERFTOOLS / SRC / PERFMON / LARGEINT.AS_ / LARGEINT.AS
Encoding:
Text File  |  1993-02-11  |  20.8 KB  |  845 lines

  1.         TITLE   "Large Integer Arithmetic"
  2. ;++
  3. ;
  4. ; Module Name:
  5. ;
  6. ;    largeint.s
  7. ;
  8. ; Abstract:
  9. ;
  10. ;    This module implements routines for performing extended integer
  11. ;    arithmtic.
  12. ;
  13. ; Environment:
  14. ;
  15. ;    Any mode.
  16. ;
  17. ; Revision History:
  18. ;
  19. ;--
  20.  
  21. .386p
  22.         .xlist
  23. include ks386.inc
  24. include callconv.inc            ; calling convention macros
  25.         .list
  26.  
  27.  
  28. _TEXT   SEGMENT DWORD USE32 PUBLIC 'CODE'
  29.         ASSUME  CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  30.  
  31.         page ,132
  32.         subttl  "LargeIntegerAdd"
  33. ;++
  34. ;
  35. ; LARGE_INTEGER
  36. ; LargeIntegerAdd (
  37. ;    IN LARGE_INTEGER Addend1,
  38. ;    IN LARGE_INTEGER Addend2
  39. ;    )
  40. ;
  41. ; Routine Description:
  42. ;
  43. ;    This function adds a signed large integer to a signed large integer and
  44. ;    returns the signed large integer result.
  45. ;
  46. ; Arguments:
  47. ;
  48. ;    (TOS+4) = Addend1 - first addend value
  49. ;    (TOS+12) = Addend2 - second addend value
  50. ;
  51. ; Return Value:
  52. ;
  53. ;    The large integer result is stored in (edx:eax)
  54. ;
  55. ;--
  56.  
  57. cPublicProc _LargeIntegerAdd ,4
  58. cPublicFpo 4,0
  59.  
  60.         mov     eax,[esp]+4             ; (eax)=add1.low
  61.         add     eax,[esp]+12            ; (eax)=sum.low
  62.         mov     edx,[esp]+8             ; (edx)=add1.hi
  63.         adc     edx,[esp]+16            ; (edx)=sum.hi
  64.         stdRET    _LargeIntegerAdd
  65.  
  66. stdENDP _LargeIntegerAdd
  67.  
  68.  
  69.         page
  70.         subttl  "Enlarged Integer Multiply"
  71. ;++
  72. ;
  73. ; LARGE_INTEGER
  74. ; EnlargedIntegerMultiply (
  75. ;    IN LONG Multiplicand,
  76. ;    IN LONG Multiplier
  77. ;    )
  78. ;
  79. ; Routine Description:
  80. ;
  81. ;    This function multiplies a signed integer by an signed integer and
  82. ;    returns a signed large integer result.
  83. ;
  84. ; Arguments:
  85. ;
  86. ;    (TOS+4) = Factor1
  87. ;    (TOS+8) = Factor2
  88. ;
  89. ; Return Value:
  90. ;
  91. ;    The large integer result is stored in (edx:eax)
  92. ;
  93. ;--
  94.  
  95. cPublicProc _EnlargedIntegerMultiply ,2
  96. cPublicFpo 2,0
  97.  
  98.         mov     eax,[esp]+4             ; (eax) = factor1
  99.         imul    dword ptr [esp]+8       ; (edx:eax) = signed result
  100.         stdRET    _EnlargedIntegerMultiply
  101.  
  102. stdENDP _EnlargedIntegerMultiply
  103.  
  104.  
  105.         page
  106.         subttl  "Enlarged Unsigned Integer Multiply"
  107. ;++
  108. ;
  109. ; LARGE_INTEGER
  110. ; EnlargedUnsignedMultiply (
  111. ;    IN ULONG Multiplicand,
  112. ;    IN ULONG Multiplier
  113. ;    )
  114. ;
  115. ; Routine Description:
  116. ;
  117. ;    This function multiplies an un signed integer by an unsigned integer and
  118. ;    returns a signed large integer result.
  119. ;
  120. ; Arguments:
  121. ;
  122. ;    (TOS+4) = Factor1
  123. ;    (TOS+8) = Factor2
  124. ;
  125. ; Return Value:
  126. ;
  127. ;    The large integer result is stored in (edx:eax)
  128. ;
  129. ;--
  130.  
  131. cPublicProc _EnlargedUnsignedMultiply ,2
  132. cPublicFpo 2,0
  133.  
  134.         mov     eax,[esp]+4             ; (eax) = factor1
  135.         mul     dword ptr [esp]+8       ; (edx:eax) = unsigned result
  136.         stdRET    _EnlargedUnsignedMultiply
  137.  
  138. stdENDP _EnlargedUnsignedMultiply
  139.  
  140.         page
  141.         subttl  "Enlarged Unsigned Integer Divide"
  142.  
  143. ;++
  144. ;
  145. ; ULONG
  146. ; EnlargedUnsignedDivide (
  147. ;    IN ULARGE_INTEGER Dividend,
  148. ;    IN ULONG Divisor,
  149. ;    IN PULONG Remainder
  150. ;    )
  151. ;
  152. ;
  153. ; Routine Description:
  154. ;
  155. ;    This function divides an unsigned large integer by an unsigned long
  156. ;    and returns the resultant quotient and optionally the remainder.
  157. ;
  158. ;    N.B. It is assumed that no overflow will occur.
  159. ;
  160. ; Arguments:
  161. ;
  162. ;    Dividend - Supplies the dividend value.
  163. ;
  164. ;    Divisor - Supplies the divisor value.
  165. ;
  166. ;    Remainder - Supplies an optional pointer to a variable that
  167. ;        receives the remainder.
  168. ;
  169. ; Return Value:
  170. ;
  171. ;    The unsigned long integer quotient is returned as the function value.
  172. ;
  173. ;--
  174.  
  175. cPublicProc _EnlargedUnsignedDivide,4
  176. cPublicFpo 4,0
  177.  
  178.         mov     eax, [esp+4]            ; (eax) = Dividend.LowPart
  179.         mov     edx, [esp+8]            ; (edx) = Dividend.HighPart
  180.         mov     ecx, [esp+16]           ; (ecx) = pRemainder
  181.         div     dword ptr [esp+12]      ; divide by Divisor
  182.  
  183.         or      ecx, ecx                ; return remainder?
  184.         jnz     short @f
  185.  
  186.         stdRET    _EnlargedUnsignedDivide    ; (eax) = Quotient
  187.  
  188. align 4
  189. @@:     mov     [ecx], edx              ; save remainder
  190.         stdRET    _EnlargedUnsignedDivide    ; (eax) = Quotient
  191.  
  192. stdENDP _EnlargedUnsignedDivide
  193.  
  194.         page
  195.         subttl  "Extended Large Integer Divide"
  196.  
  197. ;++
  198. ;
  199. ; LARGE_INTEGER
  200. ; ExtendedLargeIntegerDivide (
  201. ;     IN LARGE_INTEGER Dividend,
  202. ;     IN ULONG Divisor,
  203. ;     OUT PULONG Remainder OPTIONAL
  204. ;     )
  205. ;
  206. ; Routine Description:
  207. ;
  208. ;     This routine divides an unsigned 64 bit dividend by a 32 bit divisor
  209. ;     and returns a 64-bit quotient, and optionally the 32-bit remainder.
  210. ;
  211. ;
  212. ; Arguments:
  213. ;
  214. ;     Dividend - Supplies the 64 bit dividend for the divide operation.
  215. ;
  216. ;     Divisor - Supplies the 32 bit divisor for the divide operation.
  217. ;
  218. ;     Remainder - Supplies an optional pointer to a variable which receives
  219. ;         the remainder
  220. ;
  221. ; Return Value:
  222. ;
  223. ;     The 64-bit quotient is returned as the function value.
  224. ;
  225. ;--
  226.  
  227. cPublicProc _ExtendedLargeIntegerDivide, 4
  228. cPublicFpo 4,3
  229.  
  230.         push    esi
  231.         push    edi
  232.         push    ebx
  233.  
  234.         mov     eax, [esp+16]       ; (eax) = Dividend.LowPart
  235.         mov     edx, [esp+20]       ; (edx) = Dividend.HighPart
  236.  
  237. lid00:  mov     ebx, [esp+24]       ; (ebx) = Divisor
  238.         or      ebx, ebx
  239.         jz      short lid_zero      ; Attempted a divide by zero
  240.  
  241.         push    ebp
  242.  
  243.         mov     ecx, 64             ; Loop count
  244.         xor     esi, esi            ; Clear partial remainder
  245.  
  246. ; (edx:eax) = Dividend
  247. ; (ebx) = Divisor
  248. ; (ecx) = Loop count
  249. ; (esi) = partial remainder
  250.  
  251. align 4
  252. lid10:  shl     eax, 1              ; (LowPart << 1)  | 0
  253.         rcl     edx, 1              ; (HighPart << 1) | CF
  254.         rcl     esi, 1              ; (Partial << 1)  | CF
  255.  
  256.         sbb     edi, edi            ; clone CF into edi (0 or -1)
  257.  
  258.         cmp     esi, ebx            ; check if partial remainder less then divisor
  259.         cmc
  260.         sbb     ebp, ebp            ; clone CF intp ebp
  261.         or      edi, ebp            ; merge with remainder of high bit
  262.  
  263.         sub     eax, edi            ; merge quotient bit
  264.         and     edi, ebx            ; Select divisor or 0
  265.         sub     esi, edi
  266.  
  267.         dec     ecx                 ; dec interration count
  268.         jnz     short lid10         ; go around again
  269.  
  270.         pop     ebp
  271.         pop     ebx
  272.         pop     edi
  273.  
  274.         mov     ecx, [esp+20]       ; (ecx) = Remainder
  275.         or      ecx, ecx
  276.         jnz     short lid20
  277.  
  278.         pop     esi
  279.         stdRET  _ExtendedLargeIntegerDivide
  280.  
  281. align 4
  282. lid20:
  283.         mov     [ecx], esi          ; store remainder
  284.         pop     esi
  285.         stdRET  _ExtendedLargeIntegerDivide
  286.  
  287. lid_zero:
  288.         div     dword ptr [esp+24]  ; cause divide by zero exception
  289.         pop     ebx
  290.         pop     edi
  291.         pop     esi
  292.         stdRET  _ExtendedLargeIntegerDivide
  293. stdENDP     _ExtendedLargeIntegerDivide
  294.  
  295.         page
  296.         subttl  "Extended Magic Divide"
  297. ;++
  298. ;
  299. ; LARGE_INTEGER
  300. ; ExtendedMagicDivide (
  301. ;    IN LARGE_INTEGER Dividend,
  302. ;    IN LARGE_INTEGER MagicDivisor,
  303. ;    IN CCHAR ShiftCount
  304. ;    )
  305. ;
  306. ; Routine Description:
  307. ;
  308. ;    This function divides a signed large integer by an unsigned large integer
  309. ;    and returns the signed large integer result. The division is performed
  310. ;    using reciprocal multiplication of a signed large integer value by an
  311. ;    unsigned large integer fraction which represents the most significant
  312. ;    64-bits of the reciprocal divisor rounded up in its least significant bit
  313. ;    and normalized with respect to bit 63. A shift count is also provided
  314. ;    which is used to truncate the fractional bits from the result value.
  315. ;
  316. ; Arguments:
  317. ;
  318. ;   (ebp+8) = Dividend
  319. ;   (ebp+16) = MagicDivisor value is a 64-bit multiplicative reciprocal
  320. ;   (ebp+24) = ShiftCount - Right shift adjustment value.
  321. ;
  322. ; Return Value:
  323. ;
  324. ;    The large integer result is stored  in (edx:eax)
  325. ;
  326. ;--
  327.  
  328. RemdDiv     equ [ebp+8]             ; Dividend
  329. RemdRec     equ [ebp+16]            ; Reciprocal (magic divisor)
  330. RemdShift   equ [ebp+24]
  331. RemdTmp1    equ [ebp-4]
  332. RemdTmp2    equ [ebp-8]
  333. RemdTmp3    equ [ebp-12]
  334.  
  335. cPublicProc _ExtendedMagicDivide ,5
  336.  
  337.         push    ebp
  338.         mov     ebp,esp
  339.         sub     esp,12
  340.         push    esi
  341.  
  342.         mov     esi, RemdDiv+4
  343.         test    esi,80000000h
  344.         jz      remd10                  ; no sign, no need to negate
  345.  
  346.         neg     dword ptr RemdDiv+4
  347.         neg     dword ptr RemdDiv
  348.         sbb     dword ptr RemdDiv+4,0   ; negate
  349.  
  350. remd10: mov     eax,RemdRec
  351.         mul     dword ptr RemdDiv       ; (edx:eax) = Div.lo * Rec.lo
  352.         mov     RemdTmp1,edx
  353.  
  354.         mov     eax,RemdRec
  355.         mul     dword ptr RemdDiv+4     ; (edx:eax) = Div.hi * Rec.lo
  356.         mov     RemdTmp2,eax
  357.         mov     RemdTmp3,edx
  358.  
  359.         mov     eax,RemdRec+4
  360.         mul     dword ptr RemdDiv       ; (edx:eax) = Div.lo * Rec.hi
  361.  
  362. ;
  363. ;   Col 0 doesn't matter
  364. ;   Col 1 = Hi(Div.lo * Rec.lo) + Low(Div.Hi * Rec.lo) + Low(Div.lo * Rec.hi)
  365. ;         = RemdTmp1 + RemdTmp2 + eax
  366. ;         -> Only want carry from Col 1
  367. ;
  368.  
  369.         xor     ecx,ecx                 ; (ecx) = 0
  370.         add     eax,RemdTmp1
  371.         adc     ecx, 0                  ; save carry in ecx
  372.         add     eax,RemdTmp2
  373.         adc     ecx, 0                  ; Save Carry, all we want from Col2
  374.  
  375.         mov     RemdTmp1,edx
  376.  
  377.         mov     eax,RemdRec+4
  378.         mul     dword ptr RemdDiv+4     ; (edx:eax) = Div.Hi * Rec.Hi
  379.  
  380. ;
  381. ;   TOS = carry flag from Col 1
  382. ;
  383. ;   Col 2 = Col1 CF +
  384. ;           Hi(Div.Hi * Rec.Lo) + Hi(Div.Lo * Rec.Hi) + Low(Div.Hi * Rec.Hi)
  385. ;         = CF + RemdTmp3 + RemdTmp1 + eax
  386. ;
  387. ;   Col 3 = Col2 CF + Hi(Div.Hi * Rec.Hi)
  388. ;         = CF + edx
  389. ;
  390.  
  391.         add     eax,RemdTmp1
  392.         adc     edx, 0                  ; add carry to edx
  393.         add     eax,RemdTmp3            ; (eax) = col 2
  394.         adc     edx, 0                  ; add carry to edx
  395.         add     eax, ecx
  396.         adc     edx, 0                  ; (edx) = col 3
  397.  
  398. ;
  399. ;   (edx:eax) = the high 64 bits of the multiply, shift it right by
  400. ;               shift count to discard bits to right of virtual decimal pt.
  401. ;
  402. ;   RemdShift could be as large as 63 and still not 0 the result, 386
  403. ;   will only shift 31 bits at a time, so must do the sift multiple
  404. ;   times to get correct effect.
  405. ;
  406.  
  407.         mov     cl,RemdShift
  408. remd20: cmp     cl,31
  409.         jbe     remd30
  410.         sub     cl,31
  411.         shrd    eax,edx,31
  412.         shr     edx,31
  413.         jmp     remd20
  414.  
  415. remd30: shrd    eax,edx,cl
  416.         shr     edx,cl
  417.  
  418. ;
  419. ;   Negate the result if need be
  420. ;
  421.  
  422.         test    esi,80000000h
  423.         jz      remd40                  ; no sign, go return without negate
  424.  
  425.         neg     edx
  426.         neg     eax
  427.         sbb     edx,0
  428.  
  429. ;
  430. ;   Store the result
  431. ;
  432.  
  433. remd40:
  434.         ; results in (edx:eax)
  435.  
  436.         pop     esi
  437.         mov     esp,ebp
  438.         pop     ebp
  439.         stdRET    _ExtendedMagicDivide
  440.  
  441. stdENDP _ExtendedMagicDivide
  442.  
  443.  
  444.         page
  445.         subttl  "Extended Integer Multiply"
  446. ;++
  447. ;
  448. ; LARGE_INTEGER
  449. ; ExtendedIntegerMultiply (
  450. ;    IN LARGE_INTEGER Multiplicand,
  451. ;    IN ULONG Multiplier
  452. ;    )
  453. ;
  454. ; Routine Description:
  455. ;
  456. ;    This function multiplies a signed large integer by a signed integer and
  457. ;    returns the signed large integer result.
  458. ;
  459. ; Arguments:
  460. ;
  461. ;   (ebp+8,12)=multiplican (MCAN)
  462. ;   (ebp+16)=multiplier (MPER)
  463. ;
  464. ; Return Value:
  465. ;
  466. ;    The large integer result is stored in (edx:eax)
  467. ;
  468. ;--
  469.  
  470. ReimMCAN    equ [ebp+8]
  471. ReimMPER    equ [ebp+16]
  472.  
  473. cPublicProc _ExtendedIntegerMultiply ,3
  474.  
  475.         push    ebp
  476.         mov     ebp,esp
  477.         push    esi
  478.  
  479.         mov     esi,ReimMPER
  480.         xor     esi,ReimMCAN+4              ; (esi) = result sign
  481.  
  482.         test    ReimMCAN+4,80000000h
  483.         jz      short reim10                ; MCAN pos, go look at MPER
  484.  
  485.         neg     dword ptr ReimMCAN+4
  486.         neg     dword ptr ReimMCAN
  487.         sbb     dword ptr ReimMCAN+4,0      ; negate multiplican
  488.  
  489. reim10: test    ReimMPER,80000000h
  490.         jz      short reim20                ; MPER pos, go do multiply
  491.  
  492.         neg     dword ptr ReimMPER          ; negate multiplier
  493.  
  494. reim20: mov     eax,ReimMPER
  495.         mul     dword ptr ReimMCAN          ; (edx:eax) = MPER * MCAN.low
  496.         push    edx
  497.         mov     ecx, eax
  498.         mov     eax,ReimMPER
  499.         mul     dword ptr ReimMCAN+4        ; (edx:eax) = MPER * MCAN.high
  500.         add     eax,[esp]                   ; (eax) = hi part of MPER*MCAN.low
  501.                                             ;   plus low part of MPER*MCAN.hi
  502.  
  503.         test    esi,80000000h
  504.         jz      short reim30                ; result sign is OK, go return
  505.  
  506.         neg     eax
  507.         neg     ecx
  508.         sbb     eax,0                       ; negate result
  509.  
  510. reim30: add     esp,4                       ; clean eax off stack
  511.         pop     esi                         ; restore nonvolatile reg
  512.         mov     edx,eax                     ; (edx:ecx) = result
  513.         mov     eax,ecx                     ; (edx:eax) = result
  514.  
  515.         pop     ebp
  516.         stdRET    _ExtendedIntegerMultiply
  517.  
  518. stdENDP _ExtendedIntegerMultiply
  519.  
  520.         page
  521.         subttl  "Large Integer Shift Left"
  522. ;++
  523. ;
  524. ; LARGE_INTEGER
  525. ; LargeIntegerShiftLeft (
  526. ;     IN LARGE_INTEGER LargeInteger,
  527. ;     IN CCHAR ShiftCount
  528. ;     )
  529. ;
  530. ;
  531. ; Routine Description:
  532. ;
  533. ;     This routine does a left logical shift of a large integer by a
  534. ;     specified amount (ShiftCount) modulo 64.
  535. ;
  536. ; Arguments:
  537. ;
  538. ;     LargeInteger - Supplies the large integer to be shifted
  539. ;
  540. ;     ShiftCount - Supplies the left shift count
  541. ;
  542. ; Return Value:
  543. ;
  544. ;     LARGE_INTEGER - Receives the shift large integer result
  545. ;
  546. ;--
  547. cPublicProc _LargeIntegerShiftLeft,3
  548. cPublicFpo 3,0
  549.  
  550.         mov     ecx, [esp+12]           ; (ecx) = ShiftCount
  551.         and     ecx, 3fh                ; mod 64
  552.  
  553.         cmp     ecx, 32
  554.         jnc     short sl10
  555. ;
  556. ;  Shift count is less then 32 bits.
  557. ;
  558.         mov     eax, [esp+4]            ; (eax) = LargeInteger.LowPart
  559.         mov     edx, [esp+8]            ; (edx) = LargeInteger.HighPart
  560.         shld    edx, eax, cl
  561.         shl     eax, cl
  562.  
  563.         stdRET  _LargeIntegerShiftLeft
  564.  
  565. align 4
  566. sl10:
  567. ;
  568. ;  Shift count is greater than or equal 32 bits - low half of result is zero,
  569. ;  high half is the low half shifted left by remaining count.
  570. ;
  571.         mov     edx, [esp+4]            ; (edx) = LargeInteger.LowPart
  572.         xor     eax, eax                ; store lowpart
  573.         shl     edx, cl                 ; store highpart
  574.  
  575.         stdRET  _LargeIntegerShiftLeft
  576.  
  577. stdENDP _LargeIntegerShiftLeft
  578.  
  579.         page
  580.         subttl  "Large Integer Shift Right"
  581.  
  582. ;--
  583. ;
  584. ;LARGE_INTEGER
  585. ;LargeIntegerShiftRight (
  586. ;    IN LARGE_INTEGER LargeInteger,
  587. ;    IN CCHAR ShiftCount
  588. ;    )
  589. ;
  590. ;Routine Description:
  591. ;
  592. ;    This routine does a right logical shift of a large integer by a
  593. ;    specified amount (ShiftCount) modulo 64.
  594. ;
  595. ;Arguments:
  596. ;
  597. ;    LargeInteger - Supplies the large integer to be shifted
  598. ;
  599. ;    ShiftCount - Supplies the right shift count
  600. ;
  601. ;Return Value:
  602. ;
  603. ;    LARGE_INTEGER - Receives the shift large integer result
  604. ;
  605. ;--*/
  606. cPublicProc _LargeIntegerShiftRight,3
  607. cPublicFpo 3,0
  608.  
  609.         mov     ecx, [esp+12]           ; (ecx) = ShiftCount
  610.         and     ecx, 3fh                ; mod 64
  611.  
  612.         cmp     ecx, 32
  613.         jnc     short sr10
  614.  
  615. ;
  616. ;  Shift count is less then 32 bits.
  617. ;
  618.         mov     eax, [esp+4]            ; (eax) = LargeInteger.LowPart
  619.         mov     edx, [esp+8]            ; (edx) = LargeInteger.HighPart
  620.         shrd    eax, edx, cl
  621.         shr     edx, cl
  622.  
  623.         stdRET  _LargeIntegerShiftRight
  624.  
  625. align 4
  626. sr10:
  627. ;
  628. ;  Shift count is greater than or equal 32 bits - high half of result is zero,
  629. ;  low half is the high half shifted right by remaining count.
  630. ;
  631.         mov     eax, [esp+8]            ; (eax) = LargeInteger.HighPart
  632.         xor     edx, edx                ; store highpart
  633.         shr     eax, cl                 ; store lowpart
  634.  
  635.         stdRET  _LargeIntegerShiftRight
  636.  
  637. stdENDP _LargeIntegerShiftRight
  638.  
  639. ;++
  640. ;
  641. ;LARGE_INTEGER
  642. ;LargeIntegerArithmeticShift (
  643. ;    IN LARGE_INTEGER LargeInteger,
  644. ;    IN CCHAR ShiftCount
  645. ;    )
  646. ;
  647. ;Routine Description:
  648. ;
  649. ;    This routine does a right arithmetic shift of a large integer by a
  650. ;    specified amount (ShiftCount) modulo 64.
  651. ;
  652. ;Arguments:
  653. ;
  654. ;    LargeInteger - Supplies the large integer to be shifted
  655. ;
  656. ;    ShiftCount - Supplies the right shift count
  657. ;
  658. ;Return Value:
  659. ;
  660. ;    LARGE_INTEGER - Receives the shift large integer result
  661. ;
  662. ;--
  663. cPublicProc _LargeIntegerArithmeticShift,3
  664. cPublicFpo 3,0
  665.  
  666.         mov     ecx, [esp+12]           ; (ecx) = ShiftCount
  667.         and     ecx, 3fh                ; mod 64
  668.  
  669.         cmp     ecx, 32
  670.         jc      short sar10
  671.  
  672. ;
  673. ;  Shift count is greater than or equal 32 bits - high half of result is sign
  674. ;  bit, low half is the high half shifted right by remaining count.
  675. ;
  676.         mov     eax, [esp+8]            ; (eax) = LargeInteger.HighPart
  677.         sar     eax, cl                 ; store highpart
  678.         bt      eax, 31                 ; sign bit set?
  679.         sbb     edx, edx                ; duplicate sign bit into highpart
  680.  
  681.         stdRET  _LargeIntegerArithmeticShift
  682.  
  683. align 4
  684. sar10:
  685. ;
  686. ;  Shift count is less then 32 bits.
  687. ;
  688. ;
  689.         mov     eax, [esp+4]            ; (eax) = LargeInteger.LowPart
  690.         mov     edx, [esp+8]            ; (edx) = LargeInteger.HighPart
  691.         shrd    eax, edx, cl
  692.         sar     edx, cl
  693.  
  694.         stdRET  _LargeIntegerArithmeticShift
  695.  
  696. stdENDP _LargeIntegerArithmeticShift,3
  697.  
  698.  
  699.         page
  700.         subttl  "Large Integer Negate"
  701. ;++
  702. ;
  703. ; LARGE_INTEGER
  704. ; LargeIntegerNegate (
  705. ;    IN LARGE_INTEGER Subtrahend
  706. ;    )
  707. ;
  708. ; Routine Description:
  709. ;
  710. ;    This function negates a signed large integer and returns the signed
  711. ;    large integer result.
  712. ;
  713. ; Arguments:
  714. ;
  715. ;   (TOS+4) = Subtrahend
  716. ;
  717. ; Return Value:
  718. ;
  719. ;    The large integer result is stored in (edx:eax)
  720. ;
  721. ;--
  722.  
  723. cPublicProc _LargeIntegerNegate  ,2
  724. cPublicFpo 2,0
  725.  
  726.         mov     eax,[esp]+4             ; (eax) = lo
  727.         mov     edx,[esp]+8
  728.         neg     edx                     ; (edx) = 2's comp of hi part
  729.         neg     eax                     ; if ((eax) == 0) CF = 0
  730.                                         ; else CF = 1
  731.         sbb     edx,0                   ; (edx) = (edx) - CF
  732.                                         ; (edx:eax) = result
  733.         stdRET    _LargeIntegerNegate
  734.  
  735. stdENDP _LargeIntegerNegate
  736.  
  737.  
  738.         page
  739.         subttl  "Large Integer Subtract"
  740. ;++
  741. ;
  742. ; LARGE_INTEGER
  743. ; LargeIntegerSubtract (
  744. ;    IN LARGE_INTEGER Minuend,
  745. ;    IN LARGE_INTEGER Subtrahend
  746. ;    )
  747. ;
  748. ; Routine Description:
  749. ;
  750. ;    This function subtracts a signed large integer from a signed large
  751. ;    integer and returns the signed large integer result.
  752. ;
  753. ; Arguments:
  754. ;
  755. ;    (TOS+4) = Minuend
  756. ;    (TOS+12) = Subtrahend
  757. ;
  758. ; Return Value:
  759. ;
  760. ;    The large integer result is stored in (edx:eax)
  761. ;
  762. ;--
  763.  
  764. cPublicProc _LargeIntegerSubtract    ,4
  765. cPublicFpo 4,0
  766.  
  767.         mov     eax,[esp]+4
  768.         sub     eax,[esp]+12            ; (eax) = result.low
  769.         mov     edx,[esp]+8
  770.         sbb     edx,[esp]+16            ; (edx) = result.high
  771.         stdRET    _LargeIntegerSubtract
  772.  
  773. stdENDP _LargeIntegerSubtract
  774.  
  775.         page
  776.         subttl  "Convert Long to Large Integer"
  777. ;++
  778. ;
  779. ; LARGE_INTEGER
  780. ; ConvertLongToLargeInteger (
  781. ;     IN LONG SignedInteger
  782. ;     )
  783. ;
  784. ; Routine Description:
  785. ;
  786. ;     This function converts the input signed integer to a signed large
  787. ;     integer and returns the latter as the result.
  788. ;
  789. ; Arguments:
  790. ;
  791. ;   (TOS+4) = SignedInteger
  792. ;
  793. ; Return Value:
  794. ;
  795. ;    The large integer result is stored (edx:eax)
  796. ;
  797. ;--
  798.  
  799. cPublicProc _ConvertLongToLargeInteger   ,1
  800. cPublicFpo 1,0
  801.  
  802.         mov     eax,[esp]+4             ; (eax) = SignedInteger
  803.         cdq                             ; (edx:eax) = signed LargeInt
  804.         stdRET    _ConvertLongToLargeInteger
  805.  
  806. stdENDP _ConvertLongToLargeInteger
  807.  
  808.  
  809.         page
  810.         subttl  "Convert Ulong to Large Integer"
  811. ;++
  812. ;
  813. ; LARGE_INTEGER
  814. ; ConvertUlongToLargeInteger (
  815. ;     IN LONG UnsignedInteger
  816. ;     )
  817. ;
  818. ; Routine Description:
  819. ;
  820. ;     This function converts the input unsigned integer to a signed large
  821. ;     integer and returns the latter as the result.
  822. ;
  823. ; Arguments:
  824. ;
  825. ;   (TOS+4) = UnsignedInteger
  826. ;
  827. ; Return Value:
  828. ;
  829. ;    The large integer result is stored in (edx:eax)
  830. ;
  831. ;--
  832.  
  833. cPublicProc _ConvertUlongToLargeInteger  ,1
  834. cPublicFpo 1,0
  835.  
  836.         mov     eax,[esp]+4             ; store low
  837.         xor     edx,edx                 ; store 0 in high
  838.         stdRET    _ConvertUlongToLargeInteger
  839.  
  840. stdENDP _ConvertUlongToLargeInteger
  841.  
  842.  
  843. _TEXT   ends
  844.         end
  845.